using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using MES_workbench.Api.Implementationlayer.IServices;
using MES_workbench.Api.DTO;
using MES_workbench.Domian.Entities;
using MES_workbench.ErrorCode;
using MES_workbench.Infraetructure;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Caching.Memory;

namespace MES_workbench.Api.Implementationlayer.Services
{
    /// <summary>
    /// 工作台实现类
    /// </summary>
    public class WorkbenchServices:IWorkbenchServices
    {
        private readonly ILogger<WorkbenchServices> logger;
        private readonly EFDbContext db;
        private readonly IMemoryCache cache;

        // 预编译查询：按时间范围获取 DataStatistics 列表（无跟踪 + 排序）
        // 使用 CompileQuery（返回 IQueryable），便于直接使用 EF 的 ToListAsync 扩展方法
        private static readonly Func<EFDbContext, DateTime, DateTime, IQueryable<DataStatistics>> CompiledRangeQuery =
            EF.CompileQuery((EFDbContext ctx, DateTime start, DateTime end) =>
                ctx.DataStatistics
                   .AsNoTracking()
                   .Where(x => x.PlannedStartTime.HasValue && x.PlannedStartTime.Value >= start && x.PlannedStartTime.Value <= end)
                   .OrderBy(x => x.PlannedStartTime)
            );

        public WorkbenchServices(ILogger<WorkbenchServices> _logger, EFDbContext db, IMemoryCache cache)
        {
            logger = _logger;
            this.db = db;
            this.cache = cache;
        }

        /// <summary>
        /// 直接获取公告全量数据，按最新接收时间倒序（无需查询参数）
        /// </summary>
        /// <param name="onlyNotDeleted">是否仅返回未删除数据，默认 true</param>
        /// <returns>ApiResult 包装的 Notice 列表</returns>
        public async Task<ApiResult<List<Notice>>> GetLatestNoticesAsync(bool onlyNotDeleted = true)
        {
            var result = new ApiResult<List<Notice>>();
            try
            {
                logger.LogInformation("[Notice] 直接获取公告，OnlyNotDeleted={Only}", onlyNotDeleted);

                var q = db.Notices.AsNoTracking();
                if (onlyNotDeleted)
                {
                    q = q.Where(x => x.IsDelete == false);
                }

                var list = await q
                    .OrderByDescending(x => x.ReceiveTime)
                    .ToListAsync();

                result.success(list, "查询成功");
                logger.LogInformation("[Notice] 返回 {Count} 条公告（倒序）", list.Count);
            }
            catch (Exception ex)
            {
                logger.LogError(ex, "[Notice] 获取公告异常: {Message}", ex.Message);
                result.msg = "查询异常";
            }
            return result;
        }

        /// <summary>
        /// 按时间范围查询数据统计（最近7天/最近1个月/最近1年）
        /// </summary>
        /// <param name="dto">时间范围参数："7d" | "1m" | "1y"</param>
        /// <returns>ApiResult 包装的 DataStatistics 列表</returns>
        public async Task<ApiResult<List<DataStatistics>>> GetDataStatisticsAsync(DataStatisticsQueryDto dto)
        {
            var result = new ApiResult<List<DataStatistics>>();
            try
            {
                if (dto == null || string.IsNullOrWhiteSpace(dto.Range))
                {
                    logger.LogWarning("[DataStatistics] 入参为空或Range未提供");
                    result.msg = "参数无效";
                    return result;
                }

                DateTime now = DateTime.Now;
                DateTime start;
                switch (dto.Range.Trim().ToLower())
                {
                    case "7d":
                        start = now.AddDays(-7);
                        break;
                    case "1m":
                        start = now.AddMonths(-1);
                        break;
                    case "1y":
                        start = now.AddYears(-1);
                        break;
                    default:
                        logger.LogWarning("[DataStatistics] 未知的Range: {Range}", dto.Range);
                        result.msg = "未知的时间范围";
                        return result;
                }

                // Debug级别下才执行诊断，以避免生产环境额外查询
                if (logger.IsEnabled(LogLevel.Debug))
                {
                    var total = await db.DataStatistics.AsNoTracking().CountAsync();
                    DateTime? minTime = await db.DataStatistics.AsNoTracking()
                        .Where(x => x.PlannedStartTime.HasValue)
                        .Select(x => x.PlannedStartTime!.Value)
                        .DefaultIfEmpty()
                        .MinAsync();
                    DateTime? maxTime = await db.DataStatistics.AsNoTracking()
                        .Where(x => x.PlannedStartTime.HasValue)
                        .Select(x => x.PlannedStartTime!.Value)
                        .DefaultIfEmpty()
                        .MaxAsync();
                    logger.LogDebug("[DataDiagnostics] 总记录数={Total}, 最小时间={Min}, 最大时间={Max}", total, minTime, maxTime);
                }

                logger.LogInformation("[DataStatistics] 查询开始，范围={Range}, Start={Start}, End={End}", dto.Range, start, now);

                // 构建缓存Key：按范围 + 粗粒度时间窗口，避免频繁穿透
                var cacheKey = $"data-stats:{dto.Range}:{start:yyyyMMddHH}:{now:yyyyMMddHH}";
                if (cache.TryGetValue(cacheKey, out List<DataStatistics> cached))
                {
                    logger.LogInformation("[DataStatistics] 命中缓存，返回 {Count} 条", cached.Count);
                    result.success(cached, "查询成功(缓存)");
                    return result;
                }

                // 使用预编译查询（IQueryable）并异步物化；若失败则降级到普通查询
                List<DataStatistics> list;
                try
                {
                    list = await CompiledRangeQuery(db, start, now).ToListAsync();
                }
                catch (Exception ex)
                {
                    logger.LogError(ex, "[DataStatistics] 预编译查询失败，降级普通查询: {Message}", ex.Message);
                    list = await db.DataStatistics
                        .AsNoTracking()
                        .Where(x => x.PlannedStartTime.HasValue && x.PlannedStartTime.Value >= start && x.PlannedStartTime.Value <= now)
                        .OrderBy(x => x.PlannedStartTime)
                        .ToListAsync();
                }

                // 设置短期缓存（根据业务可调整到 30-120 秒）
                cache.Set(cacheKey, list, new MemoryCacheEntryOptions
                {
                    AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(60),
                    Size = null // 可按需配置大小上限
                });

                result.success(list, "查询成功");
                logger.LogInformation("[DataStatistics] 查询成功，返回 {Count} 条", list.Count);
            }
            catch (Exception ex)
            {
                logger.LogError(ex, "[DataStatistics] 查询异常: {Message}", ex.Message);
                result.msg = "查询异常";
            }
            return result;
        }


        /// <summary>
        /// 获取订单交付提醒全量数据，按最新交付时间倒序（无需查询条件）。
        /// </summary>
        /// <returns>ApiResult 包装的 OrderDeliveryReminder 列表</returns>
        public async Task<ApiResult<List<OrderDeliveryReminder>>> GetLatestOrderDeliveryRemindersAsync()
        {
            var result = new ApiResult<List<OrderDeliveryReminder>>();
            try
            {
                logger.LogInformation("[OrderDelivery] 获取最新订单交付提醒（无筛选条件）");

                var list = await db.orderDeliveryReminders
                    .AsNoTracking().Where(x=>x.IsDelete.Equals(false))
                    .OrderByDescending(x => x.DeliveryTime)
                    .ToListAsync();

                result.success(list, "查询成功");
                logger.LogInformation("[OrderDelivery] 返回 {Count} 条记录（按交付时间倒序）", list.Count);
            }
            catch (Exception ex)
            {
                logger.LogError(ex, "[OrderDelivery] 获取最新订单交付提醒异常: {Message}", ex.Message);
                result.msg = "查询异常";
            }
            return result;
        }

        /// <summary>
        /// 获取工单提醒全量数据（无查询条件），按主键ID倒序。
        /// </summary>
        /// <returns>ApiResult 包装的 WorkOrderReminder 列表</returns>
        public async Task<ApiResult<List<WorkOrderReminder>>> GetLatestWorkOrderRemindersAsync()
        {
            var result = new ApiResult<List<WorkOrderReminder>>();
            try
            {
                logger.LogInformation("[WorkOrderReminder] 获取最新工单提醒（无筛选条件）");

                var list = await db.WorkOrderReminders
                    .AsNoTracking()
                    .Where(x => x.IsDelete == false)
                    .OrderByDescending(x => x.WorkOrderId)
                    .ToListAsync();

                result.success(list, "查询成功");
                logger.LogInformation("[WorkOrderReminder] 返回 {Count} 条记录（按ID倒序）", list.Count);
            }
            catch (Exception ex)
            {
                logger.LogError(ex, "[WorkOrderReminder] 获取最新工单提醒异常: {Message}", ex.Message);
                result.msg = "查询异常";
            }
            return result;
        }

        /// <summary>
        /// 获取工序提醒全量数据（无查询条件），按主键ID倒序。
        /// </summary>
        /// <returns>ApiResult 包装的 ProcessStepReminder 列表</returns>
        public async Task<ApiResult<List<ProcessStepReminder>>> GetLatestProcessStepRemindersAsync()
        {
            var result = new ApiResult<List<ProcessStepReminder>>();
            try
            {
                logger.LogInformation("[ProcessStepReminder] 获取最新工序提醒（无筛选条件）");

                var list = await db.ProcessStepReminders
                    .AsNoTracking()
                    .Where(x => x.IsDelete == false)
                    .OrderByDescending(x => x.ProcessStepId)
                    .ToListAsync();

                result.success(list, "查询成功");
                logger.LogInformation("[ProcessStepReminder] 返回 {Count} 条记录（按ID倒序）", list.Count);
            }
            catch (Exception ex)
            {
                logger.LogError(ex, "[ProcessStepReminder] 获取最新工序提醒异常: {Message}", ex.Message);
                result.msg = "查询异常";
            }
            return result;
        }

        /// <summary>
        /// 获取“快过期”物品数据：还剩1天或2天到期的记录。
        /// 窗口为：[今天+1天 00:00, 今天+3天 00:00)，按到期日倒序返回。
        /// 例如今天为 8/27，则返回 8/28 与 8/29 当天到期的数据。
        /// </summary>
        /// <returns>ApiResult 包装的 ItemsApproachingExpiry 列表</returns>
        public async Task<ApiResult<List<ItemsApproachingExpiry>>> GetItemsNotExpiredAsync()
        {
            var result = new ApiResult<List<ItemsApproachingExpiry>>();
            try
            {
                // 目标区间：[Today+1d 00:00, Today+3d 00:00) —— 覆盖“剩余1天”和“剩余2天”两种情况
                var oneDayLaterStart = DateTime.Today.AddDays(1);
                var threeDaysLaterStart = DateTime.Today.AddDays(3);
                logger.LogInformation("[ItemsApproachingExpiry] 查询快过期数据（还剩1~2天到期）ExpiryDate in [{Start} , {End})", oneDayLaterStart, threeDaysLaterStart);

                var list = await db.ItemsApproachingExpirys
                    .AsNoTracking()
                    .Where(x => x.IsDelete == false
                                && x.ExpiryDate.HasValue
                                && x.ExpiryDate.Value >= oneDayLaterStart
                                && x.ExpiryDate.Value < threeDaysLaterStart)
                    .OrderByDescending(x => x.ExpiryDate)
                    .ToListAsync();

                result.success(list, "查询成功");
                logger.LogInformation("[ItemsApproachingExpiry] 返回 {Count} 条快过期记录（还剩1~2天到期，按到期日倒序）", list.Count);
            }
            catch (Exception ex)
            {
                logger.LogError(ex, "[ItemsApproachingExpiry] 查询1~2天后到期数据异常: {Message}", ex.Message);
                result.msg = "查询异常";
            }
            return result;
        }

        /// <summary>
        /// 获取即将到期物品中“已过期”的数据（ExpiryDate < 当前时间），按到期日倒序。
        /// </summary>
        /// <returns>ApiResult 包装的 ItemsApproachingExpiry 列表</returns>
        public async Task<ApiResult<List<ItemsApproachingExpiry>>> GetItemsExpiredAsync()
        {
            var result = new ApiResult<List<ItemsApproachingExpiry>>();
            try
            {
                var now = DateTime.Now;
                logger.LogInformation("[ItemsApproachingExpiry] 查询已过期数据（ExpiryDate < {Now}）", now);

                var list = await db.ItemsApproachingExpirys
                    .AsNoTracking()
                    .Where(x => x.IsDelete == false && x.ExpiryDate.HasValue && x.ExpiryDate.Value < now)
                    .OrderByDescending(x => x.ExpiryDate)
                    .ToListAsync();

                result.success(list, "查询成功");
                logger.LogInformation("[ItemsApproachingExpiry] 返回 {Count} 条已过期记录（按到期日倒序）", list.Count);
            }
            catch (Exception ex)
            {
                logger.LogError(ex, "[ItemsApproachingExpiry] 查询已过期数据异常: {Message}", ex.Message);
                result.msg = "查询异常";
            }
            return result;
        }
    }
}
